home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / misc / emu / APCNames12a.lha / APCNames / Sources.Unix / APCNames.c next >
Encoding:
C/C++ Source or Header  |  1994-01-07  |  12.4 KB  |  431 lines

  1. /* $Revision Header *** Header built automatically - do not edit! ***********
  2.  *
  3.  *    (C) Copyright 1993 by Rainer Koppler
  4.  *
  5.  *    Name .....: APCNames.c
  6.  *    Created ..: Friday 5-Mar-93 19:31:41
  7.  *    Revision .: 6
  8.  *
  9.  *    Date        Author                 Comment
  10.  *    =========   ====================   ====================
  11.  *    07-Dec-93   Rainer Koppler         enhanced encoding of long names
  12.  *    23-Sep-93   Rainer Koppler         "S:APCNames.types" support added
  13.  *    09-Sep-93   Rainer Koppler         Symantec C++ support added
  14.  *    15-Jul-93   Rainer Koppler         MS-Word support added
  15.  *    23-Mar-93   Rainer Koppler         Bug fix: multiple periods handled
  16.  *      17-Mar-93   Rainer Koppler         Bug fix: disk entry only at root level
  17.  *    05-Mar-93   Rainer Koppler         Created this file!
  18.  *
  19.  ****************************************************************************
  20.  *
  21.  *      Utility for creating original file names for MS-DOS file names
  22.  *      from the APCINFO.DAT file created by the Mac tool AccessPC.
  23.  *
  24.  * $Revision Header ********************************************************/
  25.  
  26. #include "APCNames.h"
  27. #include "Types.h"
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <ctype.h>
  32.  
  33. #ifndef AMIGA
  34. extern int strnicmp (char *, char *, int);
  35. extern int stricmp (char *, char *);
  36. #endif
  37.  
  38. /*-------------------------------------------------------------------
  39. **  SetPattern/NextEntry are my own Amiga-specific pattern-matching
  40. **   routines. I suppose there is no need for them for UNIX... :^)
  41. **-------------------------------------------------------------------
  42. */
  43.  
  44. #ifdef AMIGA
  45. #include "Wildcard.h"
  46. #else
  47. #ifndef SEEK_SET
  48. #define    SEEK_SET    0
  49. #define    SEEK_CUR    1
  50. #define    SEEK_END    2
  51. #endif
  52. #ifndef EXIT_FAILURE
  53. #define EXIT_FAILURE 1
  54. #endif
  55. static char *fnDummy;
  56. static void  SetPattern (char *fileName)
  57.   fnDummy = fileName;
  58. }
  59. static char *NextEntry (void)
  60. {  
  61.   char *fn = fnDummy;
  62.   fnDummy = NULL;
  63.   return fn;
  64. }
  65. #endif
  66.  
  67.  
  68. /*-------------------------------------------------------------------
  69. **  Each APCINFO.DAT file consists of several records denoting
  70. **  disk or file entries. Each record has a length of 80 bytes.
  71. **  The first record always denotes a disk entry, all subsequent
  72. **  records are file entries.
  73. **  After each 12 entries there are 64 bytes with undefined contents.
  74. **-------------------------------------------------------------------
  75. */
  76.  
  77. #define APC_ENTRY_SIZE  sizeof(union APCEntry)
  78. #define APC_PAD_SIZE    0x40
  79.  
  80. union APCEntry {
  81.  
  82.   UBYTE    ae_Data[80];
  83.  
  84.   struct DiskEntry {
  85.     UBYTE  de_Length;        /*length of disk name*/
  86.     UBYTE  de_Pad[79];       /*disk name and other data*/
  87.   } de;
  88.  
  89.   struct FileEntry {
  90.     UBYTE  fe_Length;        /*length of file name*/
  91.     char   fe_Name[31];      /*file name characters*/
  92.     ULONG  fe_Type;          /*Macintosh type ID*/
  93.     ULONG  fe_Creator;       /*Macintosh creator ID*/
  94.     UBYTE  fe_Pad1[23];      /*undocumented data*/
  95.     UBYTE  fe_Flags;         /*file visible <=> 0 (?)*/
  96.     char   fe_MSDOSName[8];  /*file name padded with blanks*/
  97.     char   fe_MSDOSExt[3];   /*extension padded with blanks*/
  98.     UBYTE  fe_Pad2[5];       /*always zero*/
  99.   } fe;
  100.  
  101. };
  102.  
  103.  
  104. /*----------------------------- global data ---------------------------------*/
  105.  
  106. static FILE *apcInfoDat;
  107. static union APCEntry *entry,*tstEntry;
  108. static char lngName[32],shtName[13],*sptr;
  109.  
  110. static const char versionStr[] = {
  111.   "\0$VER: APCNames 1.2 by Rainer Koppler (7.12.93)"
  112. };
  113.  
  114.  
  115. /*---------------- disk entry for empty disk (view by name) -----------------*/
  116.  
  117. static ULONG de_Empty[] = {
  118.   0x0A526169, 0x6E657220, 0x31001600, 0x0002A002,
  119.   0x02000000, 0x00000000, 0x00000000, 0x00000001,
  120.   0x002E0008, 0x00EA019C, 0x01000070, 0x02480200,
  121.   0xFFF8FFF0, 0x00000000, 0x00008000, 0x00000002,
  122.   0x7FA95F49, 0x6E736967, 0x6E696100, 0x00000000
  123. };
  124.  
  125. /*------------------------- universal file entry ----------------------------*/
  126.  
  127. static ULONG fe_Default[] = {
  128.   0x00000000, 0x00000000, 0x00000000, 0x00000000,
  129.   0x000D0D90, 0x0000000F, 0x000000E5, 0x000D0D90,
  130.   0x00000000, 0x00000000, 0x0100FFFF, 0xFFFF0000, /* TYPE, CREATOR, ... */
  131.   0x00000000, 0x00000000, 0x00000000, 0x00000000,
  132.   0x00000000, 0x00000000, 0x00000000, 0x00000000
  133. };
  134.  
  135.  
  136. /*---------------------------------------------------------------------------*/
  137.  
  138. static void Pas2CStr (UBYTE *ps, char *cs)
  139. {
  140.  UBYTE len = *ps;
  141.  
  142.  strncpy(cs,(char *)ps+1,len);
  143.  *(cs+len) = '\0';
  144. }
  145.  
  146. /*---------------------------------------------------------------------------*/
  147.  
  148. static void C2PasStr (char *cs, UBYTE *ps)
  149. {
  150.  UBYTE len = strlen(cs);
  151.  
  152.  strcpy((char *)ps+1,cs);
  153.  *ps = len;
  154. }
  155.  
  156. /*---------------------------------------------------------------------------*/
  157.  
  158. static void Long2Short (char *fileName)
  159. {
  160.   char *dotPtr,*lptr,ch,orgCh;
  161.   struct TCInfo *tci;
  162.   int i,stubIdx,state;
  163.   LONG fp;
  164.  
  165. /*--- copy entry template to "entry" and insert TYPE/CREATOR ---*/
  166.   memcpy(entry,fe_Default,APC_ENTRY_SIZE);
  167.   tci = TCInfoFor(fileName);
  168.   entry->fe.fe_Type = tci->tci_Type;
  169.   entry->fe.fe_Creator =tci->tci_Creator;
  170. /*--- insert original file name ---*/
  171.   C2PasStr(fileName,(UBYTE *)entry);
  172. /*--- 1. encode original file name to "shtName" (MS-DOS format) ---*/
  173.   for(i=0,sptr=shtName,lptr=fileName; i<8 && *lptr!='\0' && *lptr!='.';
  174.       sptr++,lptr++,i++)
  175.     *sptr = toupper(*lptr);
  176.   stubIdx = lptr-fileName; /* where the stub character would be placed */
  177.   if(stubIdx == 8) stubIdx--;
  178.   dotPtr = strchr(fileName,'.');
  179.   if(dotPtr) {
  180.     for(; i<8; i++,sptr++) *sptr = ' ';
  181.     for(lptr=dotPtr+1; i<11 && *lptr!='\0'; lptr++)
  182.       if(*lptr != '.') {
  183.         *sptr = toupper(*lptr);
  184.         sptr++;
  185.         i++;
  186.       }
  187.   }
  188.   for(; i<11; i++,sptr++) *sptr = ' ';
  189. /*--- 2. seek existing entry with same MS-DOS name & modify new name if so ---*/
  190.   fseek(apcInfoDat,0L,SEEK_SET);
  191.   state = 0;
  192.   orgCh = shtName[stubIdx];
  193.   while(fread(tstEntry,APC_ENTRY_SIZE,1,apcInfoDat) > 0) {
  194.     if(!strncmp(tstEntry->fe.fe_MSDOSName,shtName,11)) {
  195.       do {
  196.         if(state == 0)
  197.           ch = '&';
  198.         else if(state>=1 && state<=10)
  199.           ch = '0'+state-1;
  200.         else if(state>=11 && state<=36)
  201.           ch = 'A'+state-11;
  202.         else {
  203.           printf("*** Encoding possibilities exceeded. Try to rename some files.\n");
  204.           exit(EXIT_FAILURE);
  205.         }
  206.         state++;
  207.       } while(ch == orgCh);
  208.       shtName[stubIdx] = ch;
  209.     }
  210.     fp = ftell(apcInfoDat);
  211.     if(fp % 0x0400 == 0x03C0)
  212.       fread(tstEntry,APC_PAD_SIZE,1,apcInfoDat);
  213.   }
  214. /*--- 3. insert MS-DOS file name into entry & prepare "shtName" for rename ---*/
  215.   for(i=0,sptr=shtName,lptr=entry->fe.fe_MSDOSName; i<11; i++,sptr++,lptr++) 
  216.     *lptr = *sptr;
  217.   for(i=0,sptr=shtName,lptr=entry->fe.fe_MSDOSName; i<11; i++) {
  218.     if(i==8 && dotPtr && *(dotPtr+1)) {
  219.       *sptr = '.';
  220.       sptr++;
  221.     }
  222.     if(*lptr != ' ') {
  223.       *sptr = *lptr;
  224.       sptr++;
  225.     }
  226.     lptr++;
  227.   }
  228.   *sptr = 0;
  229. }
  230.  
  231. /*---------------------------------------------------------------------------*/
  232.  
  233. static void Short2Long (void)
  234. {
  235.   int i;
  236.   char *ptr;
  237.  
  238.   if(entry->fe.fe_Length > 31) {
  239.     *shtName = '\0'; *lngName = '\0';
  240.     return;
  241.   }
  242.   Pas2CStr((UBYTE *)entry,lngName);
  243.   sptr = shtName;
  244.   ptr = entry->fe.fe_MSDOSName;
  245.   for(i=0; i<8 && *ptr!=' '; sptr++,ptr++,i++)
  246.     *sptr = *ptr;
  247.   ptr = entry->fe.fe_MSDOSExt;
  248.   if(*ptr != ' ') {
  249.     *sptr = '.';
  250.     sptr++;
  251.   }
  252.   for(i=0; i<3 && *ptr!=' '; sptr++,ptr++,i++)
  253.     *sptr=*ptr;
  254.   *sptr = '\0';
  255. }
  256.  
  257. /*---------------------------------------------------------------------------*/
  258.  
  259. static BOOL EntryExistsFor (char *fileName)
  260. {
  261.   BOOL fnd = FALSE;
  262.   LONG fp;
  263.  
  264.   fseek(apcInfoDat,0L,SEEK_SET);
  265.   while(!fnd && fread(entry,APC_ENTRY_SIZE,1,apcInfoDat) > 0) {
  266.     Pas2CStr((UBYTE *)entry,lngName);
  267.     if(!(fnd = !stricmp(fileName,lngName))) {
  268.       fp = ftell(apcInfoDat);
  269.       if(fp % 0x0400 == 0x03C0)
  270.         fread(entry,APC_PAD_SIZE,1,apcInfoDat);
  271.     }
  272.   }
  273.   return(fnd);
  274. }
  275.  
  276. /*---------------------------------------------------------------------------*/
  277.  
  278. main (int argc, char *argv[])
  279. {
  280.   int cnt,fnCnt,total,cIdx;
  281.   char *fn,cmdBuf[80];
  282.   LONG fp;
  283.   BOOL err = FALSE,cpyFiles = FALSE;
  284.  
  285.   printf("\n»»APCNames«« - AccessPC renaming utility v1.2 for UNIX\n\n");
  286.  
  287.   if(--argc > 0) {
  288.     err = argc==1 && strcmp(argv[1],"-x") ;
  289.     if(!err) err = argc==2 && strncmp(argv[1],"-c",2);
  290.     if(!err) err = argc>2 && strncmp(argv[1],"-c",2) && (strcmp(argv[1],"-x") &&
  291.       strncmp(argv[2],"-c",2));
  292.     cpyFiles = !strcmp(argv[1],"-x");
  293.   }
  294.  
  295.   if(err) {
  296.     printf("USAGE: %s [ -x ][ -c[<config>] <file> { <file> }]\n",argv[0]);
  297.     exit(EXIT_FAILURE);
  298.   }
  299.  
  300.   if(!(entry=malloc(APC_ENTRY_SIZE*2))) {
  301.     printf("*** No memory for entry blocks.\n");
  302.     exit(EXIT_FAILURE);
  303.   }
  304.   tstEntry = entry+APC_ENTRY_SIZE;
  305.  
  306.   fnCnt = 0;
  307.   total = 0;
  308.  
  309. /*--- transform long names to short names and create/update APCINFO file ---*/
  310.   if(argc > 1) {
  311.     cIdx = strcmp(argv[1],"-x") ? 1 : 2;
  312.     if(!(apcInfoDat=fopen("APCINFO.DAT","a+"))) {
  313.       printf("*** Cannot open APCINFO.DAT for update.\n");
  314.       exit(EXIT_FAILURE);
  315.     }
  316.   /*--- if new file then create (empty) disk entry at beginning ---*/
  317.     fseek(apcInfoDat,0L,SEEK_END);
  318.     if(ftell(apcInfoDat) == 0)
  319.       fwrite(de_Empty,1,APC_ENTRY_SIZE,apcInfoDat);
  320.   /*--- configuration file specified ? ---*/
  321.     if(strlen(argv[cIdx]) > 2)
  322.       ReadTypes(argv[cIdx]+2);
  323.     else
  324.       ReadTypes(DEFAULT_CONFIG);
  325.   /*--- process file patterns ---*/
  326.     for(cnt=cIdx+1; cnt<=argc; cnt++) {
  327.       SetPattern(argv[cnt]);
  328.       while(fn = NextEntry()) {
  329.       /*--- lookup APCINFO.DAT for existing entry ---*/
  330.         if(!EntryExistsFor(fn)) {
  331.           fseek(apcInfoDat,0L,SEEK_END);
  332.           fp = ftell(apcInfoDat);
  333.           if(fp % 0x0400 == 0x03C0) {
  334.             memset(tstEntry,0,APC_PAD_SIZE);
  335.             fwrite(tstEntry,APC_PAD_SIZE,1,apcInfoDat);
  336.           }       
  337.           Long2Short(fn);
  338.           fwrite(entry,APC_ENTRY_SIZE,1,apcInfoDat);
  339.         }
  340.         else {
  341.           printf("\"%s\" already exists, ",fn);
  342.           Short2Long();
  343.         } 
  344.         if(cpyFiles) {
  345.           printf("writing \"%s\" as \"%s\" to DOS disk...",fn,shtName);
  346.           sprintf(cmdBuf,"mwrite %s %s",fn,shtName);
  347.           if(!system(cmdBuf)) {
  348.             printf("ok\n");
  349.             fnCnt++;
  350.           }
  351.           else
  352.             printf("failed\n");
  353.         }
  354.         else {
  355.           printf("renaming \"%s\" to \"%s\"...",fn,shtName);
  356.           if(!rename(fn,shtName)) {
  357.             printf("ok\n");
  358.             fnCnt++;
  359.           }
  360.           else
  361.             printf("failed\n");
  362.         }
  363.         total++;
  364.       }
  365.     }
  366.     fclose(apcInfoDat);
  367.     printf("\n%d file(s) of %d renamed successfully.\n",fnCnt,total);
  368.     if(cpyFiles && system("mwrite APCINFO.DAT APCINFO.DAT"))
  369.       printf("*** Cannot write APCINFO.DAT to DOS disk.\n");
  370.   }
  371. /*--- get contents of APCINFO file and transform short names to long names ---*/
  372.   else {
  373.     if(cpyFiles && system("mread APCINFO.DAT APCINFO.DAT"))
  374.       printf("*** Cannot access APCINFO.DAT on DOS disk.\n");
  375.     if(!(apcInfoDat=fopen("APCINFO.DAT","r"))) {
  376.       printf("*** Cannot open APCINFO.DAT for input.\n");
  377.       exit(EXIT_FAILURE);
  378.     }
  379.     cnt = 0;
  380.     while(fread(entry,APC_ENTRY_SIZE,1,apcInfoDat) > 0) {
  381.     /*--- D I S K  E N T R Y ---*/
  382.       if(entry->fe.fe_MSDOSName[1] == '©') {
  383.         Pas2CStr((UBYTE *)entry,lngName);
  384.         printf("Disk name: %s\n\n",lngName);
  385.       }
  386.     /*--- F I L E  E N T R Y ---*/
  387.       else {
  388.       /*--- create MS-DOS name and original name of entry data ---*/
  389.         Short2Long();
  390.       /*--- rename only if valid file entry ---*/
  391.         if(entry->fe.fe_Type == TYPE_TEXT || entry->fe.fe_Type == TYPE_WDBN) {
  392.           if(cpyFiles) {
  393.             printf("reading \"%s\" as \"%s\" from DOS disk...",lngName,shtName);
  394.             sprintf(cmdBuf,"mread %s %s",shtName,lngName);
  395.             if(!system(cmdBuf)) {
  396.               printf("ok\n");
  397.               fnCnt++;
  398.             }
  399.             else
  400.               printf("failed\n");
  401.           }
  402.           else {
  403.             printf("renaming \"%s\" to \"%s\"...",shtName,lngName);
  404.             if(!rename(shtName,lngName)) {
  405.               printf("ok\n");
  406.               fnCnt++;
  407.             }
  408.             else
  409.               printf("failed\n");
  410.           }
  411.           total++;
  412.         }
  413.         else
  414.           printf("ignoring \"%s\" (\"%s\")\n",shtName,lngName);
  415.       }
  416.       cnt++;
  417.     /*--- skip 64 bytes after each 12 records ---*/
  418.       if(cnt == 12) {
  419.         fread(entry,APC_PAD_SIZE,1,apcInfoDat);
  420.         cnt = 0;
  421.       }
  422.     }
  423.     fclose(apcInfoDat);
  424.     printf("\n%d file(s) of %d renamed successfully.\n",fnCnt,total);
  425.   }
  426.   FreeTypes();
  427.  
  428.   free(entry);
  429. }
  430.